<template>
  <div v-for="(i, idx) in value" :key="idx">
    <div class="float-right mt-5 ml-2 w-[24px]">
      <Button
        v-if="!(disabled || readonly || static || isMin)"
        @click="handleDelete(idx)"
        size="small"
        type="link"
        class="text-red-700"
      >
        <template #icon>
          <CircleX :size="18" />
        </template>
      </Button>
    </div>
    <Row :gutter="8" class="form-item-group">
      <template v-for="c in configs(idx)" :key="c.key">
        <Col v-bind="c.wrapperCol" v-if="c.when(value, value[idx])">
          <FormItem v-bind="c.formItemAttrs" :label-col="c.labelCol">
            <Switch
              v-if="c.type.name === 'ASwitch'"
              v-bind="c.componentAttrs"
              :checked="Boolean(i[c?.key])"
              @update:checked="(e:any) => {
                handleChange({ key: [idx, c.key], value: e })
                c.componentAttrs.onChange?.({ update:handleChange, idx, value: i })
              }"
            />
            <component
              v-else
              :is="c.type"
              v-bind="c.componentAttrs"
              :raw="c.raw"
              :config="c"
              :value="c.key ? i[c.key] : i"
              @update:value="(e:string|number|any) => {
                if(e?.key) {
                  handleChange({ key: [idx, e.key], value: e.value });
                } else {
                  handleChange({ key:[idx, c.key ], value: e });
                }
              c.componentAttrs.onChange?.({ update:handleChange, idx, value: i })
              }"
            />
          </FormItem>
        </Col>
      </template>
    </Row>
  </div>
  <Button
    v-if="!(disabled || readonly || static || isMax)"
    @click="handleAdd"
    size="small"
    type="link"
  >
    <template #icon>
      <CirclePlus :size="18" />
    </template>
  </Button>
</template>
<script lang="tsx" setup>
import {
  Button, Col, Form, Row, Switch,
} from 'ant-design-vue';
import { CirclePlus, CircleX } from 'lucide-vue-next';
import { computed, type PropType } from 'vue';

import { type FormItemConfig } from './ConfigFormType';

const FormItem = Form.Item;
const props = defineProps({
  static: {
    type: Boolean,
    default: false,
  },
  min: {
    type: Number,
  },
  max: {
    type: Number,
  },
  readonly: {
    type: Boolean,
    default: false,
  },
  disabled: {
    type: Boolean,
    default: false,
  },
  config: {
    type: Object as PropType<{
      key: string[];
      name: (string | number)[];
      labelCol?: any;
      wrapperCol?: any;
      componentAttrs?: any;
      formItemAttrs?: any;
      raw: FormItemConfig;
    }>,
    default: () => ({
      key: '',
      name: [],
      labelCol: {},
      wrapperCol: {},
      componentAttrs: {},
      formItemAttrs: {},
      raw: {},
    }),
  },
});
const value = defineModel('value', {
  type: Array as PropType<any>,
  default: () => [],
});
const isMax = computed(() => {
  if (props.config?.raw?.attrs?.max) {
    return value.value.length >= props.config.raw.attrs.max;
  }
  return false;
});
const isMin = computed(() => {
  if (props.config.raw?.attrs?.min) {
    return value.value.length <= props.config.raw.attrs.min;
  }
  return false;
});
const configs = (idx: number) => {
  const childrenConfig = props.config.raw.children || [];
  return childrenConfig.map((child: FormItemConfig) => {
    const {
      wrapperCol,
      labelCol,
      when,
      type,
      key = '',
      attrs,
      children,
      model,
      ...rest
    } = child;
    const name = [...props.config.name, idx];
    if (key) name.push(key);
    const formItemAttrs = {
      name,
      model,
      ...rest,
    };
    const componentAttrs = {
      ...attrs,
      disabled: Boolean(props.disabled || attrs?.disabled),
      readonly: Boolean(props.readonly || attrs?.readonly),
    } as Record<string, any>;

    return {
      key,
      name,
      type,
      children,
      when: when || (() => true),
      labelCol: labelCol || props.config.labelCol || {},
      wrapperCol: wrapperCol || props.config.wrapperCol || {},
      componentAttrs,
      formItemAttrs,
      raw: child,
    };
  });
};
const emit = defineEmits(['change']);
const handleAdd = () => {
  if (props.config.raw.model) {
    const Model = props.config.raw.model;
    value.value.push(new Model());
  } else {
    const config = configs(value.value.length);
    if (config.length === 1 && !config[0].key) {
      value.value.push(config[0].componentAttrs.useNumber ? 0 : '');
      return;
    }
    const initData: any = {};
    configs(value.value.length).forEach((c: any) => {
      if (c.children) {
        // eslint-disable-next-line no-underscore-dangle
        if (c.type.__name === 'FormItemObject') {
          initData[c.key] = c.itemAttrs?.default || {};
        } else {
          initData[c.key] = c.itemAttrs?.default || [];
        }
      } else {
        initData[c.key] = c.itemAttrs?.default || null;
      }
    });
    value.value.push(initData);
  }
  emit('change', value.value);
};
const handleDelete = (idx: number) => {
  value.value.splice(idx, 1);
  emit('change', value.value);
};

const handleChange = (data: any) => {
  const [idx, k] = data.key;
  if (k) {
    value.value[idx][k] = data.value;
  } else {
    value.value[idx] = data.value;
  }
  emit('change', value.value);
};
</script>

<style lang="less" scoped>
.form-item-group {
  border: 1px solid var(--color-border-regular);
  background-color: var(--color-bg2);
  margin-bottom: 8px;
  padding: 12px 4px 0;
  border-radius: 6px;
  :deep(.ant-form-item) {
    margin-bottom: 12px;
  }
  .form-item-group {
    background-color: var(--color-bg1);
  }
}
</style>
